#include "ProfileState.h"
#include "MenuState.h"
#include "WorldState.h"
#include "GamePlayState.h"

#include "..\Game.h"

#include "..\Bitmap Font\BitmapFont.h"

#include "..\..\SGD Wrappers\SGD_AudioManager.h"
#include "..\..\SGD Wrappers\SGD_GraphicsManager.h"
#include "..\..\SGD Wrappers\SGD_InputManager.h"
#include "..\..\SGD Wrappers\SGD_String.h"

#include <Windows.h>
#include <fstream>

/**************************************************************/
// GetInstance
//	- store the ONLY instance in global memory
//	- return the only instance by pointer
/*static*/ ProfileState* ProfileState::GetInstance(void)
{
	static ProfileState s_Instance;

	return &s_Instance;
}

void ProfileState::Enter()
{
	SGD::GraphicsManager* Graphics = SGD::GraphicsManager::GetInstance();

	hPauseImage = Graphics->LoadTexture("Resource/Images/ProfileMenu.png");

	GAME->SetCurrentLevel(0);

	GAME->SetCurrentProfile(-1);

	GAME->SetStageCompleted(0);

	iLevel1 = iLevel2 = iLevel3 = -1;

	// Load Saves
	LoadSaves();

	// Start Cursor
	nCursor = 0;
}

void ProfileState::Exit()
{
	// Unload Assets
	SGD::GraphicsManager::GetInstance()->UnloadTexture(hPauseImage);
}

bool ProfileState::Update(float dt)
{
	SGD::InputManager* Input = SGD::InputManager::GetInstance();

	// Press Escape to quit
	if (KEYESCAPE)
		nCursor = 6;

	// Move cursor
	if (KEYDOWNPRESSED)
	{
		GAME->SetInput(false);
		nCursor += 2;

		// Wrap around
		if (nCursor > 6)
			nCursor = 0;
	}
	else if (KEYUPPRESSED)
	{
		GAME->SetInput(false);
		nCursor -= 2;

		if (nCursor < 0)
			nCursor = 6;
	}
	else if (KEYRIGHTPRESSED)
	{
		GAME->SetInput(false);
		if (nCursor == 0 && iLevel1 != -1)
			nCursor = 1;
		else if (nCursor == 2 && iLevel2 != -1)
			nCursor = 3;
		else if (nCursor == 4 && iLevel3 != -1)
			nCursor = 5;
	}
	else if (KEYLEFTPRESSED)
	{
		GAME->SetInput(false);
		if (nCursor == 1)
			nCursor = 0;
		else if (nCursor == 3)
			nCursor = 2;
		else if (nCursor == 5)
			nCursor = 4;
	}
	// Load Save
	if (KEYENTER)
	{
		// Which option
		if (nCursor == 0)
		{
			// Pass Save Information To Game
			Load(1);

			// Change State
			if (iLevel1 == -1)
				GAME->ChangeState(WorldState::GetInstance());
			else
				GAME->ChangeState(GamePlayState::GetInstance());

			// Exit State
			return true;
		}
		else if (nCursor == 1)
		{
			// Delete Save
			Delete(1);
			nCursor--;
		}
		else if (nCursor == 2)
		{
			// Pass Save Information To GamePlayState
			Load(2);

			// Change State
			if (iLevel2 == -1)
				GAME->ChangeState(WorldState::GetInstance());
			else
				GAME->ChangeState(GamePlayState::GetInstance());

			// Exit State
			return true;
		}
		else if (nCursor == 3)
		{
			// Delete Save
			Delete(2);
			nCursor--;
		}
		else if (nCursor == 4)
		{
			// Pass Save Information To GamePlayState
			Load(3);

			// Change State
			if (iLevel3 == -1)
				GAME->ChangeState(WorldState::GetInstance());
			else
				GAME->ChangeState(GamePlayState::GetInstance());

			// Exit State
			return true;
		}
		else if (nCursor == 5)
		{
			// Delete Save
			Delete(3);
			nCursor--;
		}
		else if (nCursor == 6)
		{
			// Change State
			GAME->ChangeState(MenuState::GetInstance());

			// Exit State
			return true;
		}
	}

	return true;
}

void ProfileState::Render()
{
	SGD::GraphicsManager* Graphics = SGD::GraphicsManager::GetInstance();

	// Get Screen Size
	SGD::Point pCenter{ GAME->GetScreenWidth(), GAME->GetScreenHeight() };

	// Display menu options
	int nSave1Color, nSave2Color, nSave3Color, nExitColor;
	nSave1Color = nSave2Color = nSave3Color = nExitColor = 210;
	int nSave1DeleteColor, nSave2DeleteColor, nSave3DeleteColor;
	nSave1DeleteColor = nSave2DeleteColor = nSave3DeleteColor = 210;

	switch (nCursor)
	{
	case 0:
		nSave1Color = 100;
		break;
	case 1:
		nSave1DeleteColor = 100;
		break;
	case 2:
		nSave2Color = 100;
		break;
	case 3:
		nSave2DeleteColor = 100;
		break;
	case 4:
		nSave3Color = 100;
		break;
	case 5:
		nSave3DeleteColor = 100;
		break;
	case 6:
		nExitColor = 100;
		break;
	}

	// Draw Save1 Menu
	SGD::Point pSaveLoc{ pCenter.x / 2 - 250, pCenter.y / 2 - 275 };
	DrawSaveMenu(pSaveLoc, iLevel1, nSave1Color, nSave1DeleteColor);

	// Draw Save2 Menu
	pSaveLoc = { pCenter.x / 2 - 250, pCenter.y / 2 - 100 };
	DrawSaveMenu(pSaveLoc, iLevel2, nSave2Color, nSave2DeleteColor);

	// Draw Save3 Menu
	pSaveLoc = { pCenter.x / 2 - 250, pCenter.y / 2 + 75 };
	DrawSaveMenu(pSaveLoc, iLevel3, nSave3Color, nSave3DeleteColor);

	// Draw Exit Option
	pSaveLoc = { pCenter.x / 2 - 250, pCenter.y / 2 + 240 };
	GAME->GetBitmapFont()->Render("Exit", pSaveLoc, 0.5f, SGD::Color{ 210, 210, (unsigned char)nExitColor });
}

void ProfileState::Save(int fileNum)
{
	std::wstring filePath = GAME->GetFilePath();
	filePath += L"\\file";
	filePath += (char)(fileNum + 48);
	filePath += L".save";
	
	std::fstream file;

	// Save Data
	file.open(filePath.c_str(), std::ios_base::out | std::ios_base::binary);
	if (file.is_open())
	{
		file.write((char*)GAME->GetCurrentLevel(), 4);
		file.close();
	}
}

void ProfileState::Load(int fileNum)
{
	std::wstring filePath = GAME->GetFilePath();
	filePath += L"\\file";
	filePath += (char)(fileNum + 48);
	filePath += L".save";

	GAME->SetCurrentProfile(fileNum);

	std::fstream file;

	// Load Data
	file.open(filePath.c_str(), std::ios_base::in | std::ios_base::binary);
	if (file.is_open())
	{
		int stage;
		file.read((char*)&stage, 4);
		GAME->SetCurrentLevel(stage);
		file.close();
	}
}

void ProfileState::Delete(int fileNum)
{
	std::wstring filePath = GAME->GetFilePath();
	filePath += L"\\file";
	filePath += (char)(fileNum + 48);
	filePath += L".save";

	std::fstream file;

	// Save Data
	file.open(filePath.c_str(), std::ios_base::out | std::ios_base::binary);
	if (file.is_open())
	{
		int stage = -1;
		file.write((char*)&stage, 4);
		file.close();
	}

	switch (fileNum)
	{
	case 1:
		iLevel1 = -1;
		break;
	case 2:
		iLevel2 = -1;
		break;
	case 3:
		iLevel3 = -1;
		break;
	}
}

void ProfileState::LoadSaves()
{
	std::wstring filePath;
	filePath = GAME->GetFilePath();
	// Load Data 1
	filePath += L"\\file1.save";

	std::fstream file;
	file.open(filePath.c_str(), std::ios_base::in | std::ios_base::binary);
	if (file.is_open())
	{
		file.read((char*)&iLevel1, 4);
		file.close();
	}

	// Load Data 2
	filePath = GAME->GetFilePath();
	filePath += L"\\file2.save";

	file.open(filePath.c_str(), std::ios_base::in | std::ios_base::binary);
	if (file.is_open())
	{
		file.read((char*)&iLevel2, 4);
		file.close();
	}

	// Load Data 3
	filePath = GAME->GetFilePath();
	filePath += L"\\file3.save";

	file.open(filePath.c_str(), std::ios_base::in | std::ios_base::binary);
	if (file.is_open())
	{
		file.read((char*)&iLevel3, 4);
		file.close();
	}
}

void ProfileState::DrawSaveMenu(SGD::Point pLoc, int saveNum, const unsigned char ucColor, const unsigned char ucDeleteColor)
{
	// Draw Save Menu
	GRAPHICS->DrawTexture(hPauseImage, pLoc, 0.0f, SGD::Vector{}, SGD::Color{ 60, 210, 210, 210 });

	// Load Save Slot Info
	if (saveNum == -1)
	{
		pLoc = { pLoc.x + 50, pLoc.y + 75 };
		GAME->GetBitmapFont()->Render("Empty", pLoc, 0.5f, SGD::Color{ 210, 210, ucColor });
	}
	else if (saveNum <= 4)
	{
		SGD::OStringStream ossSave1Info;
		ossSave1Info << "Level " << saveNum;
		pLoc = { pLoc.x + 50, pLoc.y + 75 };
		GAME->GetBitmapFont()->Render(ossSave1Info.str().c_str(), pLoc, 0.5f, SGD::Color{ 210, 210, ucColor });

		// Delete Save
		pLoc = { pLoc.x + 200, pLoc.y };
		GAME->GetBitmapFont()->Render("Delete", pLoc, 0.5f, SGD::Color{ 210, 210, ucDeleteColor });
		ossSave1Info.clear();
	}
	else
	{
		pLoc = { pLoc.x + 50, pLoc.y + 75 };
		GAME->GetBitmapFont()->Render("Completed", pLoc, 0.5f, SGD::Color{ 210, 210, ucColor });

		// Delete Save
		pLoc = { pLoc.x + 200, pLoc.y };
		GAME->GetBitmapFont()->Render("Delete", pLoc, 0.5f, SGD::Color{ 210, 210, ucDeleteColor });
	}
}